Expand description
A step-by-step PDF writer.
The entry point into the API is the Pdf
struct, which constructs the
document into one big internal buffer. The top-level writer has many methods to
create specialized writers for specific PDF objects. These all follow the same
general pattern: They borrow the main buffer mutably, expose a builder pattern
for writing individual fields in a strongly typed fashion and finish up the
object when dropped.
There are a few more top-level structs with internal buffers, like the
Content
stream builder and the Chunk
, but wherever possible buffers
are borrowed from parent writers to minimize allocations.
§Writers
The writers contained is this crate fall roughly into two categories.
Core writers enable you to write arbitrary PDF objects.
- The
Obj
writer allows to write most fundamental PDF objects (numbers, strings, arrays, dictionaries, …). It is exposed throughChunk::indirect
to write top-level indirect objects and throughArray::push
andDict::insert
to compose objects. - Streams are exposed through a separate
Chunk::stream
method since they must be indirect objects.
Specialized writers for things like a page or an image expose the core writer’s capabilities in a strongly typed fashion.
- A
Page
writer, for example, is just a thin wrapper around aDict
and it even derefs to a dictionary in case you need to write a field that is not yet exposed by the typed API. - Similarly, the
ImageXObject
derefs to aStream
, so that thefilter()
function can be shared by all kinds of streams. TheStream
in turn derefs to aDict
so that you can add arbitrary fields to the stream dictionary.
When you bind a writer to a variable instead of just writing a chained builder
pattern, you may need to manually drop it before starting a new object using
finish()
or drop()
.
§Minimal example
The following example creates a PDF with a single, empty A4 page.
use pdf_writer::{Pdf, Rect, Ref};
// Define some indirect reference ids we'll use.
let catalog_id = Ref::new(1);
let page_tree_id = Ref::new(2);
let page_id = Ref::new(3);
// Write a document catalog and a page tree with one A4 page that uses no resources.
let mut pdf = Pdf::new();
pdf.catalog(catalog_id).pages(page_tree_id);
pdf.pages(page_tree_id).kids([page_id]).count(1);
pdf.page(page_id)
.parent(page_tree_id)
.media_box(Rect::new(0.0, 0.0, 595.0, 842.0))
.resources();
// Finish with cross-reference table and trailer and write to file.
std::fs::write("target/empty.pdf", pdf.finish())?;
For more examples, check out the examples folder in the repository.
§Note
This crate is rather low-level. It does not allocate or validate indirect reference IDs for you and it does not check whether you write all required fields for an object. Refer to the PDF specification to make sure you create valid PDFs.
Modules§
- Types used by specific PDF structures.
- Strongly typed writers for specific PDF structures.
Structs§
- Writer for an array.
- A builder for a collection of indirect PDF objects.
- A builder for a content stream.
- A date, written as a text string.
- Writer for a dictionary.
- A name object.
- The null object.
- Writer for an arbitrary object.
- A builder for a PDF file.
- A rectangle, specified by two opposite corners.
- A reference to an indirect object.
- A string object (any byte sequence).
- Writer for an indirect stream object.
- A unicode text string object.
- Writer for an array of items of a fixed type.
- Writer for a dictionary mapping to a fixed type.
Enums§
- A compression filter for a stream.
Traits§
- Finish objects in postfix-style.
- A primitive PDF object.
- Rewrites a writer’s lifetime.
- A writer for a specific type of PDF object.